/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is RhinoDB, released August 08, 2008.
 * 
 * Contributor(s): Alexandru Chiculita.
 * Alternatively, the contents of this file may be used under the terms of
 * the GNU General Public License Version 2 or later (the "GPL"), in which
 * case the provisions of the GPL are applicable instead of those above. If
 * you wish to allow use of your version of this file only under the terms of
 * the GPL and not to allow others to use your version of this file under the
 * MPL, indicate your decision by deleting the provisions above and replacing
 * them with the notice and other provisions required by the GPL. If you do
 * not delete the provisions above, a recipient may use your version of this
 * file under either the MPL or the GPL.
 * 
 * ***** END LICENSE BLOCK ***** */

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;

import org.achicu.db.StorableCollection;
import org.achicu.db.StorageException;
import org.achicu.db.engines.MysqlStore;
import org.achicu.db.rhino.RhinoStorableObject;
import org.achicu.db.rhino.StorableWrapFactory;
import org.achicu.db.values.StorableInteger;
import org.achicu.db.values.StorableObject;
import org.achicu.db.values.StorableString;
import org.achicu.db.values.StorableValue;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ScriptableObject;


public class Testing {

	private static final int APPLICATION_ID = 10;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MysqlStore store = new MysqlStore();
		
		/* testBufferStore(store);
		testStoreCollections(store);*/
				
		Context context = ContextFactory.getGlobal().enterContext();
		
		ScriptableObject scope = context.initStandardObjects();
		StorableWrapFactory.initStandardWrappers(context, scope);
		
		StorableObject obj = getGlobalObject(store, APPLICATION_ID);
		
		try {
			obj.saveToStore();
			
			ScriptableObject.putProperty(scope, "storage", new RhinoStorableObject(obj, scope));
						
			Reader reader = new InputStreamReader( Testing.class.getResourceAsStream("testing.js") ); 
			
			context.evaluateReader(scope, reader, "testing.js", 0, null);
			
			obj.saveToStore();
			
		} catch (StorageException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		Context.exit();
		
		
	}
	
	
	
	public static StorableObject getGlobalObject(MysqlStore store, int appId){
		StorableObject result = null;
		int id = store.getAppBuffer(appId);
		if(id==-1){
			result = new StorableObject(store);
			try {
				result.saveToStore();
			} catch (StorageException e) {
				e.printStackTrace();
			}
			id = result.getId();
			store.setAppBuffer(appId, id);
		}else{
			result = new StorableObject(store, id);
		}
		return result;
	}
	

	private static void testBufferStore(MysqlStore store) {
		try {
			String storedString = "ana are mere";
			int storedId = store.saveBuffer(new String(storedString).getBytes("UTF-8"));
			System.out.println ( "Storing string: " +  storedId);
			
			byte[] retrievedBuffer = store.getBufferById(storedId);
			if(retrievedBuffer!=null){
				String retrievedString = new String(retrievedBuffer, "UTF-8");			
				System.out.println ( "Retrieving string: " +  retrievedString);
			}else{
				System.out.println("Retrieved buffer is null!");
			}
			
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	private static void testStoreCollections(MysqlStore store) {
		int id = createStoreCollection(store);
		
		printStoreCollection(store, id);
	}

	private static void printStoreCollection(MysqlStore store, int id) {
		StorableObject object = new StorableObject(store, id);
		
		
		try {
			StorableValue value = object.getProperty("dogs");
			System.out.println(value);
			StorableCollection collection = (StorableCollection) value;
			
			StorableObject[] objects = collection.list(0, 10);
			printDogObjects(objects, "Normal read");
			
			objects = collection.reverse().list(0, 10);
			printDogObjects(objects, "Reversed normal read");
			
			objects = collection.sortByInt("kilos").list(0, 10);
			printDogObjects(objects, "Long Ordered read");
			
			objects = collection.sortByInt("kilos").reverse().list(0, 10);
			printDogObjects(objects, "Long Ordered reverse read");
			
			
			
			objects = collection.sortByString("name").list(0, 10);
			printDogObjects(objects, "String ordered read");
			
			objects = collection.sortByString("name").reverse().list(0, 10);
			printDogObjects(objects, "String ordered reverse read");
			
			objects = collection.sortByString("name").getItems(new StorableString("Pushy"), 0, 10);
			printDogObjects(objects, "Dogs named Pushy");
			
			
			objects = collection.sortByInt("kilos").getItems(new StorableInteger(5), 0, 10);
			printDogObjects(objects, "Dogs weighting 5 kilos");
			
			
		} catch (StorageException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void printDogObjects(StorableObject[] objects, String header)
			throws StorageException {
		System.out.println("--------------------------" + header);
		for(int i=0;i<objects.length; i++){
			StorableObject obj = objects[i];
			System.out.print(obj);
			System.out.print(" - ");
			System.out.print(obj.getProperty("name"));
			System.out.print(" - ");
			System.out.println(obj.getProperty("kilos"));
		}
		System.out.println("--------------------------");
	}

	private static int createStoreCollection(MysqlStore store) {
		StorableObject object = new StorableObject(store);
		StorableCollection dogs = new StorableCollection();
		
		try {
			
			object.putProperty("dogs", dogs);
						
			dogs.push(createDog("Dogy", 15));
			dogs.push(createDog("Pushy", 25));
			dogs.push(createDog("Pushy", 45));
			dogs.push(createDog("Lexy", 5));
			dogs.push(createDog("Togy", 5));
						
			object.saveToStore();

			
		} catch (StorageException e) {

			e.printStackTrace();
			
		}
		
		return object.getId();
	}

	private static StorableObject createDog(String name, int kilos) throws StorageException {
		StorableObject dog3 = new StorableObject();
		dog3.putProperty("name", new StorableString(name));
		dog3.putProperty("kilos", new StorableInteger(kilos));
		return dog3;
	}

}
